package xyz.xiaoshengfu.xrpc.consumer;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;

import xyz.xiaoshengfu.xrpc.common.JsonUtils;
import xyz.xiaoshengfu.xrpc.config.ProviderServiceInfor;
import xyz.xiaoshengfu.xrpc.config.ReferenceBean;
import xyz.xiaoshengfu.xrpc.data.XRpcResources;
import xyz.xiaoshengfu.xrpc.data.XRpcWeightStrategy;

/**
 * <p>Title: XRpcConsumerSubscribeClient</p>
 * <p>Description: xRPC订阅服务客户端</p>
 * @author xiaoshengfu(2439323118@qq.com)
 * @date 2020年3月24日
 */
public class XRpcConsumerSubscribeClient {

	private static final Map<String, XRpcWeightStrategy> xRpcWeightStrategyMap = new ConcurrentHashMap<String, XRpcWeightStrategy>();

	public XRpcConsumerSubscribeClient() {
		super();
	}

	public void consumerFirstSubscribe() {
		List<ReferenceBean> referenceList = XRpcResources.xRpcConfig.getReferenceBeanList();
		for (int i = 0; i < referenceList.size(); i++) {
			XRpcResources.getJedisClientPool().subscribe(referenceList.get(i).getReferenceInterface(),
					new XRpcConsumerRedisSubscribe());
		}
		consumerSubscribe();
	}

	private void consumerSubscribe() {
		List<ReferenceBean> referenceList = XRpcResources.xRpcConfig.getReferenceBeanList();
		for (int i = 0; i < referenceList.size(); i++) {
			Set<String> keys = XRpcResources.getJedisClientPool()
					.keys("xRpcProvider_*" + ":" + referenceList.get(i).getReferenceInterface());
			XRpcWeightStrategy xRpcWeightStrategy = new XRpcWeightStrategy();
			for (String key : keys) {
				String value = XRpcResources.getJedisClientPool().get(key);
				if (StringUtils.isNotBlank(value)) {
					ProviderServiceInfor providerServiceInfor = JsonUtils.jsonToPojo(value, ProviderServiceInfor.class);
					if (providerServiceInfor != null) {
						xRpcWeightStrategy.addProviderServiceInfor(providerServiceInfor);
						if (!XRpcConsumerInvokeClient
								.applicationNameIsRegister(providerServiceInfor.getApplicationName())) {
							XRpcConsumerInvokeClient.registerXRpcConsumerInvokeClient(new ProviderServiceInfor(
									ProviderServiceInfor.INIT, providerServiceInfor.getProviderAddress(),
									providerServiceInfor.getProviderPort(), providerServiceInfor.getApplicationName()));
						}
					}
				}

			}
			xRpcWeightStrategyMap.put(referenceList.get(i).getReferenceInterface(), xRpcWeightStrategy);
		}
		scheduledRegisterSelfCallProviderService();
	}

	public synchronized static void onSubscribeMessage(String channel, String message) {
		//System.out.println("onSubscribeMessage:" + message);
		if (StringUtils.isNotBlank(message)) {
			ProviderServiceInfor providerServiceInfor = JsonUtils.jsonToPojo(message, ProviderServiceInfor.class);
			if (providerServiceInfor != null
					&& StringUtils.isNotBlank(providerServiceInfor.getServiceBean().getServiceInterface())
					&& StringUtils.isNotBlank(providerServiceInfor.getProviderAddress())
					&& StringUtils.isNotBlank(providerServiceInfor.getApplicationName())
					&& providerServiceInfor.getProviderPort() != null
					&& providerServiceInfor.getServerState() != null) {
				XRpcWeightStrategy xRpcWeightStrategy = xRpcWeightStrategyMap
						.get(providerServiceInfor.getServiceBean().getServiceInterface());
				XRpcConsumerInvokeClient.registerXRpcConsumerInvokeClient(
						new ProviderServiceInfor(ProviderServiceInfor.INIT, providerServiceInfor.getProviderAddress(),
								providerServiceInfor.getProviderPort(), providerServiceInfor.getApplicationName()));
				if (xRpcWeightStrategy != null) {
					xRpcWeightStrategy.addProviderServiceInfor(providerServiceInfor);
				} else {
					XRpcWeightStrategy nxRpcWeightStrategy = new XRpcWeightStrategy();
					nxRpcWeightStrategy.addProviderServiceInfor(providerServiceInfor);
					xRpcWeightStrategyMap.put(providerServiceInfor.getServiceBean().getServiceInterface(),
							nxRpcWeightStrategy);
				}
				registerSelfCallProviderService();
			}
		}

	}

	public static String weightGetXRpcApplicationName(String interfaceName) {
		XRpcWeightStrategy xRpcWeightStrategy = xRpcWeightStrategyMap.get(interfaceName);
		if (xRpcWeightStrategy != null) {
			return xRpcWeightStrategy.weightStrategyGetProviderServiceInfor().getApplicationName();
		}
		return null;
	}

	public synchronized static void removeErrorApplicationServer(String applicationName) {
		for (XRpcWeightStrategy xRpcWeightStrategy : xRpcWeightStrategyMap.values()) {
			xRpcWeightStrategy.removeProviderServiceInfor(applicationName);
		}
		registerSelfCallProviderService();
	}

	private static void registerSelfCallProviderService() {
		Map<String, List<ProviderServiceInfor>> map = new HashMap<String, List<ProviderServiceInfor>>(
				xRpcWeightStrategyMap.size());
		for (Entry<String, XRpcWeightStrategy> entry : xRpcWeightStrategyMap.entrySet()) {
			map.put(entry.getKey(), entry.getValue().getProviderServiceInforList());
		}
		XRpcResources.getJedisClientPool().setex("xRpcConsumer:" + XRpcResources.getLocalApplicationName(), 180,
				JsonUtils.objectToJson(map));
	}

	private void scheduledRegisterSelfCallProviderService() {
		Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(() -> {
			registerSelfCallProviderService();
		}, 0L, 120L, TimeUnit.SECONDS);
	}
}
